home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
winsock
/
twnsck12.zip
/
SRC\TSHOST.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-20
|
9KB
|
426 lines
/*
* TwinSock - "Troy's Windows Sockets"
*
* Copyright (C) 1994 Troy Rollo <troy@cbme.unsw.EDU.AU>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <netinet/in.h>
#include <errno.h>
#ifdef NEED_SELECT_H
#include <sys/select.h>
#endif
#include "twinsock.h"
#include "tx.h"
extern void PacketTransmitData(void *pvData, int iDataLen, int iStream);
#define BUFFER_SIZE 1024
static fd_set fdsActive;
static fd_set fdsListener;
static int nLargestFD;
static char achBuffer[BUFFER_SIZE];
static int bFlushing = 0;
void FlushInput(void);
int GetNextExpiry(struct timeval *ptvValue);
void CheckTimers(void);
extern char *sys_errlist[];
#define TIMER_ID_SEND 0
#define TIMER_ID_RECEIVE 1
#define TIMER_ID_FLUSH 2
int BumpLargestFD(int iValue)
{
if (iValue > nLargestFD)
nLargestFD = iValue;
FD_SET(iValue, &fdsActive);
};
int SetListener(int iValue)
{
FD_SET(iValue, &fdsListener);
}
int SetClosed(int iValue)
{
FD_CLR(iValue, &fdsListener);
FD_CLR(iValue, &fdsActive);
}
main(int argc, char **argv)
{
fd_set fdsRead, fdsWrite, fdsExcept, fdsDummy;
int nRead;
int i;
int iResult;
struct sockaddr_in saSource;
int nSourceLen;
int s;
struct timeval tvZero;
struct timeval tv;
fprintf(stderr, "TwinSock Host 1.1 (pre release)\n");
fprintf(stderr, "Copyright 1994 Troy Rollo\n");
fprintf(stderr, "This program is free software\n");
fprintf(stderr, "See the file COPYING for details\n");
fprintf(stderr, "\nStart your TwinSock client now\n");
fprintf(stderr, "!@$TSStart$@\n");
if (isatty(0))
InitTerm();
nLargestFD = 0;
FD_ZERO(&fdsActive);
FD_ZERO(&fdsWrite);
FD_ZERO(&fdsExcept);
FD_SET(0, &fdsActive);
while(1)
{
fdsRead = fdsActive;
iResult = select(nLargestFD + 1,
&fdsRead,
&fdsWrite,
&fdsExcept,
GetNextExpiry(&tv) ? &tv : 0);
CheckTimers();
if (iResult <= 0)
continue;
if (FD_ISSET(0, &fdsRead))
{
nRead = read(0, achBuffer, BUFFER_SIZE);
if (nRead > 0)
{
if (bFlushing)
FlushInput();
else
PacketReceiveData(achBuffer, nRead);
}
else if (nRead == 0 && !isatty(0))
{
exit(0);
}
}
for (i = 3; i <= nLargestFD; i++)
{
if (FD_ISSET(i, &fdsRead))
{
FD_ZERO(&fdsDummy);
FD_SET(i, &fdsDummy);
tvZero.tv_sec = tvZero.tv_usec = 0;
if (select(i + 1,
&fdsDummy,
&fdsWrite,
&fdsExcept,
&tvZero) != 1)
continue; /* Select lied */
nSourceLen = sizeof(saSource);
if (FD_ISSET(i, &fdsListener))
{
s = accept(i,
&saSource,
&nSourceLen);
if (s == -1)
continue;
s = htonl(s);
BumpLargestFD(s);
SendSocketData(i,
&s,
sizeof(s),
&saSource,
nSourceLen,
FN_Accept);
}
else
{
nRead = recvfrom(i,
achBuffer,
BUFFER_SIZE,
0,
&saSource,
&nSourceLen);
if (nRead < 0 &&
errno == ENOTCONN)
{
/* Was a datagram socket */
SetClosed(i);
continue;
}
if (nRead >= 0)
SendSocketData(i,
achBuffer,
nRead,
&saSource,
nSourceLen,
FN_Data);
if (nRead == 0)
SetClosed(i);
}
}
}
}
}
void
SetTransmitTimeout(void)
{
KillTimer(TIMER_ID_SEND);
SetTimer(TIMER_ID_SEND, 3000);
}
void
KillTransmitTimeout(void)
{
KillTimer(TIMER_ID_SEND);
}
void SetReceiveTimeout(void)
{
KillTimer(TIMER_ID_RECEIVE);
SetTimer(TIMER_ID_RECEIVE, 1500);
}
void KillReceiveTimeout(void)
{
KillTimer(TIMER_ID_RECEIVE);
}
static struct timeval atvTimers[3];
static int iTimersOn;
static int iTimerRunning;
static int iInTimer = 0;
int FireTimer(int iTimer)
{
switch(iTimer)
{
case TIMER_ID_SEND:
TimeoutReceived();
break;
case TIMER_ID_RECEIVE:
PacketReceiveData(0, 0);
break;
case TIMER_ID_FLUSH:
bFlushing = 0;
break;
}
}
int GetNextExpiry(struct timeval *ptvValue)
{
struct timeval tvNow;
struct timezone tzDummy;
struct timeval tvGo;
int i;
if (!iTimersOn)
return 0;
tvGo.tv_sec = 0x7fffffff;
tvGo.tv_usec = 0;
for (i = 0; i < 3; i++)
{
if (!(iTimersOn & (1 << i)))
continue;
if (atvTimers[i].tv_sec < tvGo.tv_sec ||
(atvTimers[i].tv_sec == tvGo.tv_sec &&
atvTimers[i].tv_usec < tvGo.tv_usec))
{
tvGo = atvTimers[i];
iTimerRunning = i;
}
}
gettimeofday(&tvNow, &tzDummy);
ptvValue->tv_sec = tvGo.tv_sec - tvNow.tv_sec;
ptvValue->tv_usec = tvGo.tv_usec - tvNow.tv_usec;
while (ptvValue->tv_usec < 0)
{
ptvValue->tv_usec += 1000000l;
ptvValue->tv_sec--;
}
while (ptvValue->tv_usec >= 1000000l)
{
ptvValue->tv_usec -= 1000000l;
ptvValue->tv_sec++;
}
if (ptvValue->tv_sec < 0)
{
ptvValue->tv_sec = 0;
ptvValue->tv_usec = 100;
}
if (!ptvValue->tv_sec &&
ptvValue->tv_usec < 100)
ptvValue->tv_usec = 100;
return 1;
}
void CheckTimers(void)
{
struct timeval tvNow;
struct timezone tzDummy;
int i;
gettimeofday(&tvNow, &tzDummy);
for (i = 0; i < 3; i++)
{
if (!(iTimersOn & (1 << i)))
continue;
if (atvTimers[i].tv_sec < tvNow.tv_sec ||
(atvTimers[i].tv_sec == tvNow.tv_sec &&
atvTimers[i].tv_usec < tvNow.tv_usec))
{
KillTimer(i);
FireTimer(i);
}
}
}
int SetTimer(int idTimer, int iTime)
{
struct timeval tvNow;
struct timezone tzDummy;
gettimeofday(&tvNow, &tzDummy);
atvTimers[idTimer] = tvNow;
atvTimers[idTimer].tv_usec += (long) iTime % 1000l * 1000l;
atvTimers[idTimer].tv_sec += iTime / 1000;
while (atvTimers[idTimer].tv_usec > 1000000l)
{
atvTimers[idTimer].tv_sec++;
atvTimers[idTimer].tv_usec -= 1000000l;
}
iTimersOn |= (1 << idTimer);
}
int KillTimer(int idTimer)
{
iTimersOn &= ~(1 << idTimer);
}
void Shutdown(void)
{
if (isatty(0))
UnInitTerm();
fprintf(stderr, "\nTwinSock Host Finished\n");
exit(0);
}
int
SendData(void *pvData, int iDataLen)
{
int iLen;
int nWritten;
if (bFlushing)
return iDataLen; /* Lie */
iLen = iDataLen;
while (iLen > 0)
{
nWritten = write(1, pvData, iDataLen);
if (nWritten > 0)
iLen -= nWritten;
}
return iDataLen;
}
void
FlushInput(void)
{
bFlushing = 1;
SetTimer(TIMER_ID_FLUSH, 1500);
}
static void
SendInitResponse(void)
{
struct tx_request txr;
txr.iType = htons(FN_Init);
txr.nArgs = 0;
txr.nLen = htons(10);
txr.id = -1;
txr.nError = 0;
PacketTransmitData(&txr, 10, -2);
}
void
DataReceived(void *pvData, int iLen)
{
static struct tx_request *ptxr = 0;
static struct tx_request txrHeader;
static int nBytes = 0;
short nPktLen;
enum Functions ft;
int nCopy;
while (iLen)
{
if (nBytes < 10)
{
nCopy = 10 - nBytes;
if (nCopy > iLen)
nCopy = iLen;
memcpy((char *) &txrHeader + nBytes, pvData, nCopy);
nBytes += nCopy;
pvData = (char *) pvData + nCopy;
iLen -= nCopy;
if (nBytes == 10)
{
nPktLen = ntohs(txrHeader.nLen);
ptxr = (struct tx_request *) malloc(sizeof(struct tx_request) + nPktLen - 10);
memcpy(ptxr, &txrHeader, 10);
}
}
if (nBytes >= 10)
{
nPktLen = ntohs(txrHeader.nLen);
ft = (enum Functions) ntohs(txrHeader.iType);
nCopy = nPktLen - nBytes;
if (nCopy > iLen)
nCopy = iLen;
if (nCopy)
{
memcpy((char *) ptxr + nBytes, pvData, nCopy);
nBytes += nCopy;
pvData = (char *) pvData + nCopy;
iLen -= nCopy;
}
if (nBytes == nPktLen)
{
if (ft == FN_Init)
SendInitResponse();
else
ResponseReceived(ptxr);
free(ptxr);
ptxr = 0;
nBytes = 0;
}
}
}
}